import * as Cesium from 'cesium'
// https://cesium.com/learn/cesiumjs/ref-doc/BillboardGraphics.html?classFilter=billboard
export class DomEntity {
  constructor(
    {
      id,
      position,
      html,
      horizontalOrigin = Cesium.HorizontalOrigin.LEFT,
      verticalOrigin = Cesium.VerticalOrigin.TOP,
      pixelOffset = new Cesium.Cartesian2(0, 0),
      distanceDisplayCondition = new Cesium.DistanceDisplayCondition(),
      // TODO: 待实现
      // 从上到下优先级递减
      // scaleByDistance,
      // sizeInMeters,
      // pixelOffsetScaleByDistance ,
      show = true,
    },

    viewer = window.viewer,
  ) {
    if (!Cesium.defined(html)) {
      throw new Error('未传参html')
    }

    if (!Cesium.defined(position)) {
      throw new Error('未传参 position')
    }
    this._id = id
    this._position = position
    this._html = html
    this._verticalOrigin = verticalOrigin
    this._horizontalOrigin = horizontalOrigin
    this._pixelOffset = pixelOffset
    this._distanceDisplayCondition = distanceDisplayCondition
    this._show = show
    this.viewer = viewer
    this.rootDom = null
    this.isDestroyed = false
    this.removeCallback = this.init()
  }

  init() {
    const rootDom = (this.rootDom = document.createElement('div'))

    rootDom.className = 'dom-entity outer'

    Object.assign(rootDom.style, {
      position: 'fixed',
      pointerEvents: 'none',
      // visibility: 'hidden',
      opacity: 0,
      transform: `translate(${(this._horizontalOrigin - 1) * 50}%,${(-this._verticalOrigin - 1) * 50}%)`,
    })

    if (typeof this._html === 'string') {
      rootDom.innerHTML = this._html
    } else {
      rootDom.appendChild(this._html)
    }

    document.body.appendChild(rootDom)

    const scratchCartesian2 = new Cesium.Cartesian2()

    return this.viewer.scene.preRender.addEventListener((scene, julianDate) => {
      this.viewer.scene.cartesianToCanvasCoordinates(this._position, scratchCartesian2)

      if (Cesium.defined(scratchCartesian2)) {
        rootDom.style.left = `${scratchCartesian2.x + this._pixelOffset.x}px`

        rootDom.style.top = `${scratchCartesian2.y + this._pixelOffset.y}px`

        if (this._show) {
          const distance = Cesium.Cartesian3.distance(scene.camera.position, this._position)

          const { near, far } = this._distanceDisplayCondition

          if (near < distance && distance < far) {
            if (this.judgeOcclusionByGlobe(this._position, scene)) {
              // rootDom.style.visibility = 'hidden'
              rootDom.style.opacity = 0
            } else {
              // rootDom.style.visibility = 'visible'
              rootDom.style.opacity = 1
            }
          } else {
            // rootDom.style.visibility = 'hidden'
            rootDom.style.opacity = 0
          }
        } else {
          // rootDom.style.visibility = 'hidden'

          rootDom.style.opacity = 0
        }
      }
    })
  }

  // 判断是否被地球遮挡

  judgeOcclusionByGlobe(position, scene) {
    const occluder = new Cesium.EllipsoidalOccluder(Cesium.Ellipsoid.WGS84, scene.camera.position)
    return !occluder.isPointVisible(position)
  }

  destroy() {
    if (this.isDestroyed) return

    this.removeCallback()

    document.body.removeChild(this.rootDom)
    this.isDestroyed = true
  }
  get show() {
    return this._show
  }
  set show(flag) {
    this._show = flag
    // this.rootDom.style.visibility = flag ? 'visible' : 'hidden'
    this.rootDom.style.opacity = flag ? 1 : 0
  }
}
